/**
 *       Copyright (c) 2012 Lukas Zaruba
 *
 *   This file is part of Robot Playground.
 *
 *   Robot Playground is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Robot Playground is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Lesser General Public License for more details.
 *
 *   You should have received a copy of the GNU Lesser General Public License
 *   along with Robot Playground. If not, see <http://www.gnu.org/licenses/>.
 */
package net.zarubsys.robotplayground.gui.dummydevice.monitors;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.BitSet;
import java.util.List;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import net.zarubsys.robotplayground.dummydevice.monitors.DummyPositionMonitor;
import net.zarubsys.robotplayground.dummydevice.monitors.DummyPostionMonitorEventData;
import net.zarubsys.robotplayground.gui.dummydevice.plugin.DummyDeviceGUIPlugin;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.Platform;
import org.eclipse.swt.graphics.Point;
import org.osgi.framework.Bundle;

/**
 * DummyPositionMapViewPanel
 *
 * @author Lukas Zaruba, lukas.zaruba@gmail.com
 */
public class DummyPositionMapViewPanel extends JPanel {
	
	private static final long serialVersionUID = 5218349127208912291L;
	
	private static final int BOX_SIZE = 24;
	private static final int BORDER_SIZE = 10;
	private static final Logger LOG = Logger.getLogger(DummyPositionMapViewPanel.class);
	
	private final BufferedImage car;
	private final BufferedImage obstacle;
	
	private DummyPositionMonitor monitor;

	public DummyPositionMapViewPanel() {
		setDoubleBuffered(true);
		setBackground(Color.LIGHT_GRAY);
		Bundle bundle = Platform.getBundle(DummyDeviceGUIPlugin.PLUGIN_ID);
		try {
			car = ImageIO.read(bundle.getEntry("images/car.png"));
			obstacle = ImageIO.read(bundle.getEntry("images/box.png"));
		} catch (IOException e) {
			LOG.error("Error while loading images from bundle!", e);
			throw new RuntimeException(e);
		}
	}
	
	public void setDummyPositionMonitor(DummyPositionMonitor monitor) {
		this.monitor = monitor;
	}
	
	@SuppressWarnings("unused") // data are not used YET
	public void update(DummyPostionMonitorEventData data) {
		repaint();
	}

	@Override
	public void paint(Graphics g) {
		super.paint(g);
		Assert.isLegal(g instanceof Graphics2D, "Expecting Graphic2D!!");
		Graphics2D g2d = (Graphics2D) g;
		
		if (monitor == null) return;
		
		g2d.clearRect(0, 0, getWidth(), getHeight());
		
		createGrid(g2d);
		layoutObstacles(g2d);
		drawDummyDevice(g2d);
	}

	private void createGrid(Graphics2D g2d) {
		g2d.setColor(Color.BLACK);
		int columnCount = monitor.getMap().getLineLength();
		int lineCount = monitor.getMap().getContent().size();
		
		for (int i = 0; i <= columnCount; i++) {
			g2d.drawLine(BORDER_SIZE + i * BOX_SIZE, BORDER_SIZE, BORDER_SIZE + i * BOX_SIZE, BORDER_SIZE + lineCount * BOX_SIZE);
		}
		
		for (int i = 0; i <= lineCount; i++) {
			g2d.drawLine(BORDER_SIZE, BORDER_SIZE + i * BOX_SIZE, BORDER_SIZE + columnCount * BOX_SIZE, BORDER_SIZE + i * BOX_SIZE);
		}
	}

	private void layoutObstacles(Graphics2D g2d) {
		Assert.isNotNull(monitor, "Monitor must not be null at this point!");
		List<BitSet> content = monitor.getMap().getContent();
		int i = 0;
		for (BitSet line : content) {
			for (int j = 0; j < monitor.getMap().getLineLength(); j++) {
				boolean filled = line.get(j);
				if (!filled) continue;
				g2d.drawImage(obstacle, BORDER_SIZE + j * BOX_SIZE, BORDER_SIZE + i * BOX_SIZE, null);
			}
			i++;
		}
	}

	private void drawDummyDevice(Graphics2D g2d) {
		AffineTransform transform = new AffineTransform();
		transform.rotate(Math.toRadians(monitor.getDirection()), BORDER_SIZE + monitor.getX() * BOX_SIZE + BOX_SIZE / 2, BORDER_SIZE + monitor.getY() * BOX_SIZE + BOX_SIZE / 2);
		transform.translate(BORDER_SIZE + monitor.getX() * BOX_SIZE, BORDER_SIZE + monitor.getY() * BOX_SIZE);
		g2d.drawImage(car, transform, null);
	}

	public Point getRequiredSize() {
		Assert.isNotNull(monitor, "Monitor must be set first!!!");
		return new Point(2 * BORDER_SIZE + monitor.getMap().getLineLength() * BOX_SIZE, 2 * BORDER_SIZE + monitor.getMap().getContent().size() * BOX_SIZE);
	}

}

